<script setup lang="ts">
import YkPagination from '@yk/components/pagination/YkPagination.vue'
import { Pages } from '@typings/pages'
import { Download, Plus } from '@element-plus/icons-vue'
import YkTableColumn from '@yk/components/table-column/YkTableColumn.vue'
import { ObjectUtil } from '@utils/object-util'
import { ElForm, ElTable } from 'element-plus'
import { TableUtil } from '@utils/table-util'
import {
  addAlarmRuleAPI,
  delAlarmRuleAPI,
  editAlarmRuleAPI,
  getAlarmRulePageNumByIdAPI,
  getAlarmRulesListByPageAPI,
  toggleAlarmEnableAPI
} from '@/api/alarm'
import { getDeviceListAPI, getDeviceListByCurrentUserAPI } from '@/api/device'
import { DeviceDTO } from '@/api/entity/device'
import { AlarmDTO, AlarmRuleSaveForm, ConditionDTO } from '@/api/entity/alarm'
import { ElValidator, required } from '@utils/form-rule'
import { Template, VariableDTO } from '@/api/entity/variable'
import { getVariableListByDeviceIdAPI, getVariableModelByIdAPI, getVariableModelListAPI } from '@/api/variable'
import { AlarmUtil, MountedCheck } from '@/utils'

defineOptions({ name: 'AlarmRule' })
const route = useRoute()

/**
 * 支持params参数
 * @param deviceId 【非必填】-默认选中设备
 * @param id 【非必填】-聚焦到表格的一行
 */
const mc = new MountedCheck()
onMounted(async () => {
  loadDefaultParams()
  await initFocusTableRow()
  searchHandle()
  getDeviceList()
  getDeviceAllList()
  mc.end()
})

onActivated(() => {
  if (mc.isMounted()) return
  getTableData()
})

// region TODO 聚焦某一行
let focusTableRowKey = ''
async function initFocusTableRow () {
  return new Promise((resolve) => {
    focusTableRowKey = (route.params.id as string)
    if (focusTableRowKey) {
      getAlarmRulePageNumByIdAPI({
        id: focusTableRowKey,
        ...pages.getParams()
      }).then((res) => {
        res.result().then((rdata) => {
          pages.pageNum = rdata.data || 1
          resolve(undefined)
        }).finally(() => resolve(undefined))
      }).catch(() => resolve(undefined))
    } else {
      resolve(undefined)
    }
  })
}
// 聚焦行
function focusTableRow () {
  if (focusTableRowKey) {
    nextTick(() => {
      TableUtil.highlightRow(tableDataRef.value, tableData.value.findIndex(item => item.id === focusTableRowKey))
      focusTableRowKey = ''
    })
  }
}
// endregion

// region TODO 查询
function loadDefaultParams () {
  if (route.params?.deviceId) {
    searchParams.deviceId = route.params.deviceId as string
  }
}
const searchParams = reactive({
  q: '',
  deviceId: ''
})
function searchHandle () {
  pages.pageNum = 1
  exportParams.value = ObjectUtil.copy(searchParams)
  getTableData()
}
// endregion

// region TODO 设备列表
const deviceList = shallowRef<DeviceDTO[]>(null)
function getDeviceList () {
  getDeviceListByCurrentUserAPI().then((res) => {
    res.result().then((rdata) => {
      deviceList.value = rdata.data
    })
  })
}

const deviceAllList = shallowRef<DeviceDTO[]>(null)
function getDeviceAllList () {
  getDeviceListAPI().then((res) => {
    res.result().then((rdata) => {
      deviceAllList.value = rdata.data
    })
  })
}
// endregion

// region TODO 变量模板
const variableModelList = shallowRef<Template[]>()
function getVariableModelList () {
  getVariableModelListAPI().then((res) => {
    res.result().then((rdata) => {
      variableModelList.value = rdata.data
    })
  })
}
// endregion

// region TODO 表格数据
const pages = reactive(new Pages())
const tableData = shallowRef<AlarmDTO[]>([])
const tableDataRef = shallowRef<InstanceType<typeof ElTable>>()
function getTableData () {
  const loading = ElLoading.service()
  getAlarmRulesListByPageAPI({
    ...pages.getParams(),
    param: searchParams
  }).then((res) => {
    res.result().then((rdata) => {
      tableData.value = rdata.records
      pages.total = rdata.total
      focusTableRow()
    })
  }).finally(loading.close)
}
function delTableItem (id: string) {
  ElMessageBox.confirm('删除当前触发器？', '删除提醒').then(() => {
    const loading = ElLoading.service()
    delAlarmRuleAPI({ id }).then((res) => {
      res.result().then(() => {
        getTableData()
      })
    }).finally(loading.close)
  })
}
// endregion

// region TODO 启用/禁用报警规则
function alarmEnableBeforeChange (item: AlarmDTO) {
  return new Promise<boolean>((resolve, reject) => {
    const loading = ElLoading.service()
    toggleAlarmEnableAPI({ id: item.id, enable: !item.enable }).then((res) => {
      res.result().then(() => {
        resolve(true)
      }).catch(reject)
    }).catch(reject).finally(loading.close)
  })
}
// endregion

// region TODO 导出
const exportParams = shallowRef<typeof searchParams>()
// endregion

// region TODO 添加/修改表单
const saveForm = ref(new AlarmRuleSaveForm())
const saveFormRules = {
  // 触发条件
  condition: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const _rule = saveForm.value.rule
      if (ObjectUtil.isEmpty(_rule.name)) {
        callback(Error('触发条件为必填项'))
        return
      }
      if (ObjectUtil.isEmpty(_rule.valueA)) {
        callback(Error((currentVariable.value.type === '0' ? 'A值' : '触发值') + '为必填项'))
        return
      }
      if ([3, 4].includes(_rule.name)) {
        if (ObjectUtil.isEmpty(_rule.valueB)) {
          callback(Error('B值为必填项'))
          return
        }
        const valueA = Number(_rule.valueA)
        const valueB = Number(_rule.valueB)
        if (valueB < valueA) {
          callback(Error('B值应大于A值'))
          return
        }
      }
      callback(undefined)
    },
    trigger: 'change',
    required: true
  } as ElValidator],
  // 是否推送 0-是 1-否
  inform: [required.change('是否推送为必填项')],
  // 推送类型 0-公众号 1-短信 2-播报
  informType: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      if (!informTypeList.value.length) {
        callback(Error('推送方式为必填项'))
        return
      }
      callback(undefined)
    },
    trigger: 'change',
    required: true
  } as ElValidator],
  // 触发器名称
  name: [required('触发器名称为必填项')],
  // 触发对象
  targetId: [{
    validator (rule: any, value: any, callback: (error?: Error) => void) {
      const { targetId, type, variableId } = saveForm.value
      if (!targetId) {
        callback(Error((type === '0' ? '设备' : '变量模板') + '为必填项'))
        return
      }
      if (!variableId) {
        callback(Error(('变量为必填项')))
        return
      }
      callback(undefined)
    },
    trigger: 'change',
    required: true
  } as ElValidator],
  // 触发器类型 0-设备 1-变量模版
  type: [required.change('触发器类型为必填项')],
  // 变量id
  variableId: [required('变量为必填项')]
}
const saveFormRef = shallowRef<InstanceType<typeof ElForm>>()
function submitSaveForm () {
  saveFormRef.value.validate().then(() => {
    const loading = ElLoading.service()
    loading.setText('正在保存...')
    const params = ObjectUtil.copy(saveForm.value)
    params.informType = informTypeList.value.join(',')
    const result = saveForm.value.id ? editAlarmRuleAPI(params) : addAlarmRuleAPI(params)
    result.then((res) => {
      res.result().then(() => {
        ElMessage.success('保存成功')
        closeSaveFormDialog()
        getTableData()
      })
    }).finally(loading.close)
  })
  // MessageBoxResult.confirm('网关添加成功，前往查看网关参数', '添加成功', {
  //   confirmButtonText: '调试窗口',
  //   cancelButtonText: '关闭',
  //   type: 'success'
  // })
}

// region TODO 触发器类型
// 触发器类型 - Change
function alarmRuleTypeChangeHandle () {
  saveForm.value.targetId = ''
  saveForm.value.variableId = ''
}
// endregion

// region TODO 触发对象
// 触发对象 - 模板/设备 - Change
function targetChangeHandle () {
  saveForm.value.variableId = ''
}
// endregion

// region TODO 变量列表
const variableList = shallowRef<VariableDTO[]>([])
// 变量列表
watch(() => saveForm.value.targetId, (nv) => {
  updateVariableList()
})
function updateVariableList () {
  if (saveForm.value.targetId) {
    if (saveForm.value.type === '0') {
      getVariableListByDeviceId(saveForm.value.targetId)
    } else {
      getVariableListByVariableModelId(saveForm.value.targetId)
    }
  }
}
function getVariableListByDeviceId (id: string) {
  getVariableListByDeviceIdAPI({ id }).then((res) => {
    res.result().then((rdata) => {
      variableList.value = rdata.data
    })
  })
}
function getVariableListByVariableModelId (id: string) {
  getVariableModelByIdAPI({ id }).then((res) => {
    res.result().then((rdata) => {
      variableList.value = rdata.data.vbVariableDTOS
    })
  })
}
// endregion

// region TODO 当前选择变量
const currentVariable = computed(() => saveForm.value.variableId ? variableList.value.find(item => item.id === saveForm.value.variableId) : undefined)
// 变量 - Change
function variableChangeHandle () {
  saveForm.value.rule = new ConditionDTO()
}
// endregion

// region TODO 是否推送
function informChangeHandle () {
  if (saveForm.value.inform === '1') {
    informTypeList.value = []
  }
}
// endregion

// region TODO 推送方式
const informTypeList = ref<string[]>([])
// endregion

// endregion

// region TODO 对话框
const saveFormDialogModel = ref(false)
function showSaveFormDialog (item?: AlarmDTO) {
  saveFormDialogModel.value = true
  if (!variableModelList.value) getVariableModelList()
  if (item) {
    nextTick(() => {
      ObjectUtil.assignDeep(saveForm.value, item, { deep: false })
      informTypeList.value = item.informType.split(',')
    })
  }
}
function closeSaveFormDialog () {
  saveFormRef.value.resetFields()
  saveForm.value.id = null
  informTypeList.value = []
  saveForm.value.rule = new ConditionDTO()
  saveFormDialogModel.value = false
}
// endregion
</script>

<template>
  <div class="layout_view d-flex" style="min-height: 100%">
    <div class="c_card-page w-100">
      <div class="c_card_header c_card-title bor-divider-b">报警触发器</div>
      <!--搜索表单-->
      <el-form inline class="c_form-search pt-16">
        <el-form-item label="触发器名称">
          <el-input v-model="searchParams.q" placeholder="请输入触发器名称搜索" />
        </el-form-item>
        <el-form-item>
          <el-select v-model="searchParams.deviceId" placeholder="全部设备" filterable clearable>
            <el-option value="">全部</el-option>
            <el-option v-for="item in deviceAllList" :key="item.id" :label="item.deviceName" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="searchHandle">查询</el-button>
        </el-form-item>
      </el-form>
      <!--功能栏-->
      <div class="d-flex-between">
        <el-button type="primary" :icon="Plus as any" @click="showSaveFormDialog()">添加触发器</el-button>
        <export-file url="/alarm/export" :params="exportParams">
          <el-button class="c_btn--export" :icon="Download as any">导出</el-button>
        </export-file>
      </div>
      <!--表格-->
      <el-table ref="tableDataRef" class="mt-16 c_table-page w-100" stripe :data="tableData">
        <el-table-column label="#" type="index" :index="TableUtil.indexMethod.bind(this, pages)" />
        <yk-table-column label="触发器名称" prop="name" />
        <yk-table-column label="触发器类型" prop="type">
          <template #default="scope">{{ scope.row.type === '0' ? '设备触发器' : '模板触发器' }}</template>
        </yk-table-column>
        <yk-table-column label="触发对象" prop="targetName" />
        <yk-table-column label="报警变量" prop="variableName" />
        <yk-table-column label="报警消息" prop="message">
          <template #default="scope">
            <div class="overflow-line-clamp-2">{{ scope.row.message || '/' }}</div>
          </template>
        </yk-table-column>
        <yk-table-column label="触发条件">
          <template #default="scope">{{ AlarmUtil.formatCondition(scope.row.rule) }}</template>
        </yk-table-column>
        <yk-table-column label="状态">
          <template #default="scope">
            <el-switch v-model="scope.row.enable" :before-change="alarmEnableBeforeChange.bind(this, scope.row)" />
          </template>
        </yk-table-column>
        <yk-table-column label="创建时间" prop="createdAt" sortable />
        <el-table-column>
          <template #default="scope">
            <div class="c_table-operation">
              <!--<el-link type="primary" size="small">查看</el-link>-->
              <el-link type="primary" size="small" @click="showSaveFormDialog(scope.row)">编辑</el-link>
              <el-link type="danger" size="small" @click="delTableItem(scope.row.id)">删除</el-link>
            </div>
          </template>
        </el-table-column>
      </el-table>
      <!--分页-->
      <el-affix target=".c_table-page" position="bottom" :offset="0">
        <yk-pagination class="c_table-pagination-page" :pages="pages" @handle="getTableData" />
      </el-affix>
    </div>
    <!--添加/修改表单-->
    <el-dialog
      v-model="saveFormDialogModel" :title="saveForm.id ? '编辑报警触发器' : '添加报警触发器'" width="770px"
      :close-on-click-modal="false" draggable :modal="false"
      @close="closeSaveFormDialog"
    >
      <el-form
        ref="saveFormRef" class="c_form-save mt-20" :model="saveForm"
        :rules="saveFormRules"
        label-width="140px"
      >
        <el-form-item label="触发器名称：" prop="name">
          <el-input v-model.trim="saveForm.name" placeholder="请输入触发器名称" style="width: 262px" />
        </el-form-item>
        <el-form-item label="触发器类型：" prop="type">
          <el-select v-model="saveForm.type" placeholder="请选择触发器类型" style="width: 262px" @change="alarmRuleTypeChangeHandle">
            <el-option label="设备触发器" value="0" />
            <el-option label="模板触发器" value="1" />
          </el-select>
        </el-form-item>
        <!--设备 - 触发器类型-->
        <el-form-item v-if="saveForm.type === '0'" label="选择设备和变量：" prop="targetId">
          <div class="d-flex-align-center">
            <el-select
              v-model="saveForm.targetId" placeholder="请选择设备" filterable
              @change="targetChangeHandle"
            >
              <el-option
                v-for="item in deviceList" :key="item.id" :label="item.deviceName"
                :value="item.id"
              />
            </el-select>
            <refresh-btn class="cursor-pointer ml-2 fs-24 color-primary" @click="getDeviceList" />
            <el-select
              v-model="saveForm.variableId" placeholder="请选择变量" filterable
              class="ml-12"
              @change="variableChangeHandle"
            >
              <el-option v-for="item in variableList" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
            <refresh-btn class="cursor-pointer ml-2 fs-24 color-primary" @click="updateVariableList" />
          </div>
        </el-form-item>
        <!--模板 - 触发器类型-->
        <el-form-item v-if="saveForm.type === '1'" label="选择模板和变量：" prop="targetId">
          <div class="d-flex-align-center">
            <el-select
              v-model="saveForm.targetId" placeholder="请选择模板" filterable
              @change="targetChangeHandle"
            >
              <el-option v-for="item in variableModelList" :key="item.id" :label="item.modelName" :value="item.id" />
            </el-select>
            <refresh-btn class="cursor-pointer ml-2 fs-24 color-primary" @click="getVariableModelList" />
            <el-select
              v-model="saveForm.variableId" placeholder="请选择变量" filterable
              class="ml-12"
              @change="variableChangeHandle"
            >
              <el-option v-for="item in variableList" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
            <refresh-btn class="cursor-pointer ml-2 fs-24 color-primary" @click="updateVariableList" />
          </div>
        </el-form-item>
        <template v-if="currentVariable">
          <!--模拟量 - 触发条件-->
          <el-form-item v-if="currentVariable.type === '0'" label="触发条件：" prop="condition">
            <div class="d-flex">
              <el-select v-model="saveForm.rule.name" placeholder="请选择触发条件">
                <el-option label="大于A" :value="0" />
                <el-option label="小于A" :value="1" />
                <el-option label="等于A" :value="2" />
                <el-option label="大于A并且小于B" :value="3" />
                <el-option label="小于A或者大于B" :value="4" />
              </el-select>
              <el-input-number v-model="saveForm.rule.valueA" placeholder="请输入A的值" class="ml-12 el-c-input-pure" style="width: 154px" />
              <el-input-number
                v-if="[3,4].includes(saveForm.rule.name)" v-model="saveForm.rule.valueB" placeholder="请输入B的值"
                class="ml-12 el-c-input-pure"
                style="width: 154px"
              />
            </div>
          </el-form-item>
          <!--开关量 - 触发条件-->
          <el-form-item v-if="currentVariable.type === '1'" label="触发条件：" prop="condition">
            <div class="d-flex">
              <el-select v-model="saveForm.rule.name" placeholder="请选择触发条件">
                <el-option label="等于" :value="2" />
                <el-option label="不等于" :value="5" />
              </el-select>
              <el-input-number v-model="saveForm.rule.valueA" placeholder="请输入触发值" class="ml-12 el-c-input-pure" style="width: 154px" />
            </div>
          </el-form-item>
        </template>
        <el-form-item label="报警消息" prop="message">
          <el-input v-model="saveForm.message" type="textarea" placeholder="自定义报警消息" style="width: 262px" />
        </el-form-item>
        <el-form-item label="是否推送：" prop="inform">
          <el-select v-model="saveForm.inform" placeholder="请选择是否推送" style="width: 262px" @change="informChangeHandle">
            <el-option label="是" value="0" />
            <el-option label="否" value="1" />
          </el-select>
        </el-form-item>
        <el-form-item v-if="saveForm.inform === '0'" label="推送方式：" prop="informType">
          <el-checkbox-group v-model="informTypeList">
            <el-checkbox label="0">公众号</el-checkbox>
            <el-checkbox label="1">短信</el-checkbox>
            <el-checkbox label="2">播报</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="c_form__submit-btn">
          <el-button type="primary" plain @click="closeSaveFormDialog">取消</el-button>
          <el-button type="primary" @click="submitSaveForm">确定</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped lang="scss">
</style>
